package com.ssh.dao.impl;

import java.io.Serializable;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Repository;

import com.ssh.common.log.LogFactory;
import com.ssh.common.log.LogName;
import com.ssh.common.util.Page;
import com.ssh.dao.IDao;

/**
 * hibernate的dao实现
 * @author laohuidi
 *
 */
@Repository
public class DaoImpl implements IDao {
	@Resource 
	private SessionFactory sessionFactory;
	
	/* (non-Javadoc)
	 * @see com.nyhr.boss.dao.IDao#saveOrUpdateDomain(java.lang.Object)
	 */
	public <T> T saveOrUpdateDomain(T domain) {
		curSession().saveOrUpdate(domain);
		curSession().flush();
		return domain;
	}
	
	/* (non-Javadoc)
	 * @see com.nyhr.boss.dao.IDao#curSession()
	 */
	public Session curSession() {
		return sessionFactory.getCurrentSession();
	}

	/* (non-Javadoc)
	 * @see com.nyhr.boss.dao.IDao#countAll(java.lang.String, java.lang.Object[])
	 */
	public int countAll(String sql, Object[] paramValues) {
		Query tmpQ =curSession().createQuery(sql);
		if(paramValues!=null&&paramValues.length!=0){
			for(int i=0;i<paramValues.length;i++){
				tmpQ.setParameter(i,paramValues[i]);
			}
		}
		tmpQ.setCacheable(true);
		List list = tmpQ.list();
		if (list != null && list.size() != 0){
			return Integer.parseInt(list.get(0).toString());
		}else
			return 0;
	}
	
	//NativeSTName
	public Long countByNativeSTName(String stname, List parameters) {
		Query tmpQ = sessionFactory.getCurrentSession().getNamedQuery(stname);
		if(parameters!=null&&parameters.size()!=0){
			for(int i=0;i<parameters.size();i++){
				tmpQ.setParameter(i, parameters.get(i));
			}
		}
		Long r = Long.parseLong(tmpQ.uniqueResult().toString());
		return r;
	}
	public Long countByNativeSTName(String stname, Object[] parameters) {
		Query tmpQ = sessionFactory.getCurrentSession().getNamedQuery(stname);
		if(parameters!=null&&parameters.length!=0){
			for(int i=0;i<parameters.length;i++){
				tmpQ.setParameter(i, parameters[i]);
			}
		}
		Long r = Long.parseLong(tmpQ.uniqueResult().toString());
		return r;
	}

	@Override
	public Long countBySTName(String stname, List parameters) {
		Query tmpQ = sessionFactory.getCurrentSession().getNamedQuery(stname);
		if(parameters!=null&&parameters.size()!=0){
			for(int i=0;i<parameters.size();i++){
				tmpQ.setParameter(i, parameters.get(i));
			}
		}
		Long r =  Long.parseLong(tmpQ.uniqueResult().toString());
		return r;
	}

	@Override
	public Long countBySTName(String stname, Object[] parameters) {
		Query tmpQ = sessionFactory.getCurrentSession().getNamedQuery(stname);
		if(parameters!=null&&parameters.length!=0){
			for(int i=0;i<parameters.length;i++){
				tmpQ.setParameter(i, parameters[i]);
			}
		}
		Long r =  Long.parseLong(tmpQ.uniqueResult().toString());
		return r;
	}

	@Override
	public <T> T getDomain(T object, Serializable id) {
		return (T) sessionFactory.getCurrentSession().get(object.getClass(), id);
	}

	@Override
	public List<?> findListBySTName(String stname, List parameters,
			boolean setToCache, boolean findFromCache, long start, long size) {
		Query tmpQ = sessionFactory.getCurrentSession().getNamedQuery(stname);
		if(parameters!=null&&parameters.size()!=0){
			for(int i=0;i<parameters.size();i++){
				tmpQ.setParameter(i, parameters.get(i));
			}
		}
		tmpQ.setCacheable(setToCache);

		if(start<0){
			start =0 ;
		}
		tmpQ.setFirstResult((int) start);//number from 0
		if(size!=-1){
			tmpQ.setMaxResults((int) size);
		}
		return tmpQ.list();
	}

	@Override
	public List<?> findListBySql(String sql, List parameters,boolean isNativeSql,
			boolean setToCache, boolean findFromCache, long start, long size) {
		Query query = null;
		if(isNativeSql){
			query = sessionFactory.getCurrentSession().createSQLQuery(sql);
		}else{
			query = sessionFactory.getCurrentSession().createQuery(sql);
			query.setCacheable(setToCache);
		}
		if(parameters!=null&&parameters.size()!=0){
			for(int i=0;i<parameters.size();i++){
				query.setParameter(i, parameters.get(i));
			}
		}
		if(start<0){
			start =0 ;
		}
		query.setFirstResult((int) start);//number from 0
		if(size!=-1){
			query.setMaxResults((int) size);
		}
		if(query!=null)
			return query.list();
		else
			return null;
	}

	@Override
	public List<?> findListBySql(String sql, Object[] parameters,boolean isNativeSql,
			boolean setToCache, boolean findFromCache, long start, long size) {
		Query query = null;
		if(isNativeSql){
			query = sessionFactory.getCurrentSession().createSQLQuery(sql);
		}else{
			query = sessionFactory.getCurrentSession().createQuery(sql);
			query.setCacheable(setToCache);
		}
		if(parameters!=null&&parameters.length!=0){
			for(int i=0;i<parameters.length;i++){
				query.setParameter(i,parameters[i]);
			}
		}

		if(start<0){
			start =0 ;
		}
		query.setFirstResult((int) start);//number from 0
		if(size!=-1){
			query.setMaxResults((int) size);
		}
		if(query!=null)
			return query.list();
		else
			return null;
	}

	@Override
	public List<?> findListBySTName(String stname, Object[] parameters,
			boolean setToCache, boolean findFromCache,
			long start, long size) {

		Query tmpQ = sessionFactory.getCurrentSession().getNamedQuery(stname);
		if(parameters!=null&&parameters.length!=0){
			for(int i=0;i<parameters.length;i++){
				tmpQ.setParameter(i, parameters[i]);
			}
		}
		tmpQ.setCacheable(setToCache);

		if(start<0){
			start =0 ;
		}
		tmpQ.setFirstResult((int) start);//number from 0
		if(size!=-1){
			tmpQ.setMaxResults((int) size);
		}

		return tmpQ.list();
	}

	@Override
	public Object findOneBySTName(String stname, Object[] parameters) {
		List<?> l = findListBySTName(stname,parameters,true,true,0,1);
		if(l==null || l.size()==0)
			return null;
		else
			return l.get(0);
	}

	@Override
	public Object findOneBySTName(String stname, List parameters) {
		List<?> l = findListBySTName(stname,parameters,true,true,0,1);
		if(l==null || l.size()==0)
			return null;
		else
			return l.get(0);
	}

	@Override
	public Object findOneBySql(String sql, List parameters,boolean isNativeSql,boolean setToCache, boolean findFromCache) {
		List l =findListBySql(sql, parameters, isNativeSql, setToCache, findFromCache, 0, 1);
		if(l!=null && l.size()>0)
			return l.get(0);
		else
			return null;
	}

	@Override
	public Object findOneBySql(String sql, Object[] parameters,boolean isNativeSql,boolean setToCache, boolean findFromCache) {
		List l =findListBySql(sql, parameters, isNativeSql, setToCache, findFromCache, 0, 1);
		if(l!=null && l.size()>0)
			return l.get(0);
		else
			return null;
	}

	@Override
	public Object findOneByNativeSTName(String stname, Object[] parameters) {
		List<?> l = findListByNativeSTName(stname,parameters,true,true,0,1);
		if(l==null || l.size()==0)
			return null;
		else
			return l.get(0);
	}

	@Override
	public Object findOneByNativeSTName(String stname, List parameters) {
		List<?> l = findListByNativeSTName(stname,parameters,true,true,0,1);
		if(l==null || l.size()==0)
			return null;
		else
			return l.get(0);
	}


	@Override
	public List<?> findListByNativeSTName(String stname, Object[] parameters,
			boolean setToCache, boolean findFromCache, long start, long size) {
		Session s = sessionFactory.getCurrentSession();
		Query tmpQ = s.getNamedQuery(stname);
		if(parameters!=null&&parameters.length!=0){
			for(int i=0;i<parameters.length;i++){
				tmpQ.setParameter(i, parameters[i]);
			}
		}
		if(start<0){
			start =0 ;
		}
		tmpQ.setFirstResult((int) start);//number from 0
		if(size!=-1){
			tmpQ.setMaxResults((int) size);
		}
		return tmpQ.list();
	}

	@Override
	public List<?> findListByNativeSTName(String stname, List parameters,
			boolean setToCache, boolean findFromCache, long start, long size) {
		Session s = sessionFactory.getCurrentSession();
		Query tmpQ = s.getNamedQuery(stname);
		if(parameters!=null&&parameters.size()!=0){
			for(int i=0;i<parameters.size();i++){
				tmpQ.setParameter(i, parameters.get(i));
			}
		}
		if(start<0){
			start =0 ;
		}
		tmpQ.setFirstResult((int) start);//number from 0
		if(size!=-1){
			tmpQ.setMaxResults((int) size);
		}
		return tmpQ.list();
	}

	@Override
	public <T> T saveDomain(T object) {
		sessionFactory.getCurrentSession().saveOrUpdate(object);
		return object;
	}

	@Override
	public int executeBySTName(String stname, Object[] parameters) {
		Session s =sessionFactory.getCurrentSession();
		//versioned可以更新实体
//		String hqlVersionedUpdate = "update versioned Customer set name = :newName where name = :oldName";
		Query tmpQ = s.getNamedQuery(stname);
		if(parameters!=null&&parameters.length!=0){
			for(int i=0;i<parameters.length;i++){
				tmpQ.setParameter(i, parameters[i]);
			}
		}
		int i=tmpQ.executeUpdate();
		return i;
	}

	@Override
	public int executeBySTName(String stname, List parameters) {
		Session s =sessionFactory.getCurrentSession();
		//versioned可以更新实体
//		String hqlVersionedUpdate = "update versioned Customer set name = :newName where name = :oldName";
		Query tmpQ = s.getNamedQuery(stname);
		if(parameters!=null&&parameters.size()!=0){
			for(int i=0;i<parameters.size();i++){
				tmpQ.setParameter(i, parameters.get(i));
			}
		}

		int i=tmpQ.executeUpdate();
		return i;

	}

	@Override
	public boolean deleteDomain(Class<?> clazz,Serializable id) {
		Session s = sessionFactory.getCurrentSession();
		Object tmpPO = s.load(clazz, id);
		if (tmpPO == null)
			return true;
		else
			s.delete(tmpPO);
		return true;
	}

	@Override
	public List executeProcByName(String procName, Object[] parameters) {
		Session s = sessionFactory.getCurrentSession();
		Query tmpQ = s.getNamedQuery(procName);
		if(parameters!=null&&parameters.length!=0){
			for(int i=0;i<parameters.length;i++){
				tmpQ.setParameter(i, parameters[i]);
			}
		}
		List list = tmpQ.list();
		return list;
	}

	@Override
	public <T> T getDomain(Class<T> clazz, Serializable id) {
		return (T) sessionFactory.getCurrentSession().get(clazz, id);
	}

	@Override
	public int queryIntoPage(String stName, String countStName,
			Object[] params, Page page, boolean countPage,
			boolean isNaviteSqlName) {
		try{
			if(countPage){
				if(isNaviteSqlName){
					Long c= countByNativeSTName(countStName, params);
					page.setTotalCount(c);
				}else{
					Long c= countBySTName(countStName, params);
					page.setTotalCount(c);
				}
			}
			List list = null;
			if(isNaviteSqlName){
				list = this.findListByNativeSTName(stName, params, true, true, (int)(page.getStartIndex()-1),(int) page.getNumberPerPage());
			}else{
				list = this.findListBySTName(stName, params, true, true, (int)(page.getStartIndex()-1), (int)page.getNumberPerPage());
			}
			if(page.getNumberPerPage()<=0){
				page.setNumberPerPage(page.getTotalCount());
				page.setTotalPageNum(1);
			}
			if(countPage)
				page.countTotalPageNum();
			page.setPageData(list);
		}catch(Exception e){
			LogFactory.getDefaultLog().error("", e, LogName.ERROR);
			return -1;
		}
		return 0;
	}

	@Override
	public int queryIntoPageBySql(String sqlQuery,String sqlCount,List params,Page page,boolean countPage,boolean isNaviteSqlName){
		try{
			Query q =null;
			Session session =sessionFactory.getCurrentSession();
			if(countPage){
				if(isNaviteSqlName){
					q = session.createSQLQuery(sqlCount);
				}
				else{
					q = session.createQuery(sqlCount);
				}
				if(params!=null && params.size()>0){
					for(int i=0;i<params.size();i++){
						q.setParameter(i, params.get(i));
					}
				}

				Long c= Long.parseLong(q.uniqueResult().toString());
				page.setTotalCount(c);

			}
			List list = null;
			q= null;
			if(isNaviteSqlName)
				q = session.createSQLQuery(sqlQuery);
			else{
				q = session.createQuery(sqlQuery);
				q.setCacheable(true);
			}

			if(params!=null && params.size()>0){
				for(int i=0;i<params.size();i++){
					q.setParameter(i, params.get(i));
				}
			}




			if((page.getStartIndex()-1)<0){
				q.setFirstResult(0);
			}else{
				q.setFirstResult((int)(page.getStartIndex()-1));
			}
			if(page.getNumberPerPage()!=-1){
				q.setMaxResults((int) page.getNumberPerPage());
			}

			list = q.list();

			if(page.getNumberPerPage()<=0){
				page.setNumberPerPage(page.getTotalCount());
				page.setTotalPageNum(1);
			}

			if(countPage)
				page.countTotalPageNum();

			page.setPageData(list);
		}catch(Exception e){
			LogFactory.getDefaultLog().error("", e, LogName.ERROR);
			return -1;
		}
		return 0;
	}

	@Override
	public boolean deleteDomain(Object persistentObj) {
		try {
			sessionFactory.getCurrentSession().delete(persistentObj);
			return true;
		} catch (HibernateException e) {
			return false;
		}

	}


}
